fix(html/parser): distinguish interpolations inside and outside tags#8646
fix(html/parser): distinguish interpolations inside and outside tags#8646ematipico merged 8 commits intobiomejs:mainfrom
Conversation
🦋 Changeset detectedLatest commit: f394f59 The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughThis PR introduces attribute-specific HTML text-expression node kinds (HtmlAttributeDoubleTextExpression and HtmlAttributeSingleTextExpression) and updates codegen and kinds to expose them. The HTML parser now completes text expressions inside tag contexts as attribute-specific kinds. The formatter gains formatter rules and FormatRule/AsFormat/IntoFormat impls for the new nodes, and formatter match arms were updated to use the renamed variants. Whitespace/children handling was adjusted to account for bogus elements, and tests for Django-style top-level text expressions (issue-8605) were added. Changes include test harness routing for files with text expressions. Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (4 passed)
✨ Finishing touches
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (16)
crates/biome_html_factory/src/generated/node_factory.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_html_factory/src/generated/syntax_factory.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_html_parser/tests/html_specs/error/interpolation.html.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/error/template-langs/django/issue-8605.html.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/astro/attribute_expression.astro.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/attach.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/await_multiline.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/complex_expressions.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/dynamic-prop.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/each_as_in_identifier.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/shorthand-prop.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_parser/tests/html_specs/ok/svelte/shorthand-spread-props.svelte.snapis excluded by!**/*.snapand included by**crates/biome_html_syntax/src/generated/kind.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_html_syntax/src/generated/macros.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_html_syntax/src/generated/nodes.rsis excluded by!**/generated/**,!**/generated/**and included by**crates/biome_html_syntax/src/generated/nodes_mut.rsis excluded by!**/generated/**,!**/generated/**and included by**
📒 Files selected for processing (13)
.changeset/happy-cats-drive.mdcrates/biome_html_formatter/src/generated.rscrates/biome_html_formatter/src/html/any/attribute.rscrates/biome_html_formatter/src/html/any/attribute_initializer.rscrates/biome_html_formatter/src/html/auxiliary/attribute_double_text_expression.rscrates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rscrates/biome_html_formatter/src/html/auxiliary/mod.rscrates/biome_html_formatter/src/html/lists/attribute_list.rscrates/biome_html_parser/src/syntax/mod.rscrates/biome_html_parser/tests/html_specs/error/template-langs/django/issue-8605.htmlcrates/biome_html_syntax/src/attr_ext.rsxtask/codegen/html.ungramxtask/codegen/src/html_kinds_src.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.rs: Use inline rustdoc documentation for rules, assists, and their options
Use thedbg!()macro for debugging output in Rust tests and code
Use doc tests (doctest) format with code blocks in rustdoc comments; ensure assertions pass in tests
Files:
crates/biome_html_formatter/src/html/auxiliary/mod.rsxtask/codegen/src/html_kinds_src.rscrates/biome_html_formatter/src/html/lists/attribute_list.rscrates/biome_html_formatter/src/html/auxiliary/attribute_double_text_expression.rscrates/biome_html_syntax/src/attr_ext.rscrates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rscrates/biome_html_parser/src/syntax/mod.rscrates/biome_html_formatter/src/html/any/attribute_initializer.rscrates/biome_html_formatter/src/html/any/attribute.rscrates/biome_html_formatter/src/generated.rs
🧠 Learnings (34)
📓 Common learnings
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Define `FormatHtmlSyntaxNode` struct in a `cst.rs` file implementing `FormatRule<HtmlSyntaxNode>`, `AsFormat<HtmlFormatContext>`, and `IntoFormat<HtmlFormatContext>` traits using the provided boilerplate code
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/local_inference.rs : Implement local inference in dedicated modules to derive type definitions from expressions without context of surrounding scopes
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/mod.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/*.ungram : Unions of nodes must start with `Any*`, e.g., `AnyHtmlAttribute`
Applied to files:
crates/biome_html_formatter/src/html/lists/attribute_list.rscrates/biome_html_syntax/src/attr_ext.rscrates/biome_html_parser/src/syntax/mod.rscrates/biome_html_formatter/src/html/any/attribute_initializer.rscrates/biome_html_formatter/src/html/any/attribute.rs
📚 Learning: 2025-12-19T12:53:30.413Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-12-19T12:53:30.413Z
Learning: Applies to crates/biome_analyze/**/biome_rule_options/lib/**/*.rs : Use `rename_all = "camelCase"` in serde derive macro for rule options
Applied to files:
crates/biome_html_formatter/src/html/lists/attribute_list.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : When formatting AST nodes, use mandatory tokens from the AST instead of hardcoding token strings (e.g., use `node.l_paren_token().format()` instead of `token("(")`)
Applied to files:
crates/biome_html_formatter/src/html/lists/attribute_list.rscrates/biome_html_formatter/src/html/auxiliary/attribute_double_text_expression.rscrates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rscrates/biome_html_parser/src/syntax/mod.rscrates/biome_html_formatter/src/html/any/attribute_initializer.rscrates/biome_html_formatter/src/html/any/attribute.rscrates/biome_html_formatter/src/generated.rs
📚 Learning: 2025-12-19T12:53:30.413Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-12-19T12:53:30.413Z
Learning: Applies to crates/biome_analyze/**/biome_rule_options/lib/**/*.rs : Wrap rule options fields in `Option<>` to properly track set and unset options during merge
Applied to files:
crates/biome_html_formatter/src/html/lists/attribute_list.rscrates/biome_html_formatter/src/generated.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/*.ungram : Nodes that represent a list must end with the postfix `List`, e.g., `HtmlAttributeList`, and lists are mandatory (not optional) but empty by default
Applied to files:
crates/biome_html_formatter/src/html/lists/attribute_list.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/*.ungram : All grammar nodes must start with the prefix of the language, e.g., `HtmlSimpleAttribute`
Applied to files:
crates/biome_html_formatter/src/html/lists/attribute_list.rscrates/biome_html_syntax/src/attr_ext.rscrates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rscrates/biome_html_parser/src/syntax/mod.rscrates/biome_html_formatter/src/html/any/attribute.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : Use `ParseSeparatedList` and `ParseNodeList` for parsing lists with error recovery to avoid infinite loops
Applied to files:
crates/biome_html_formatter/src/html/lists/attribute_list.rs
📚 Learning: 2025-11-24T18:05:42.356Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_type_info/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:42.356Z
Learning: Applies to crates/biome_js_type_info/**/*.rs : Use `TypeReference` instead of `Arc` for types that reference other types to avoid stale cache issues when modules are replaced
Applied to files:
crates/biome_html_formatter/src/html/lists/attribute_list.rs
📚 Learning: 2025-12-19T12:53:30.413Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-12-19T12:53:30.413Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/**/*.rs : Avoid string allocations by comparing against `&str` or using `TokenText`
Applied to files:
crates/biome_html_formatter/src/html/lists/attribute_list.rscrates/biome_html_syntax/src/attr_ext.rscrates/biome_html_parser/src/syntax/mod.rscrates/biome_html_formatter/src/html/any/attribute.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Define `FormatHtmlSyntaxNode` struct in a `cst.rs` file implementing `FormatRule<HtmlSyntaxNode>`, `AsFormat<HtmlFormatContext>`, and `IntoFormat<HtmlFormatContext>` traits using the provided boilerplate code
Applied to files:
crates/biome_html_formatter/src/html/lists/attribute_list.rscrates/biome_html_formatter/src/html/auxiliary/attribute_double_text_expression.rscrates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rscrates/biome_html_formatter/src/html/any/attribute_initializer.rscrates/biome_html_formatter/src/html/any/attribute.rscrates/biome_html_formatter/src/generated.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Import the `FormatNode` trait and implement it for your Node when creating formatters in biome_js_formatter
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_double_text_expression.rscrates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rscrates/biome_html_formatter/src/html/any/attribute_initializer.rscrates/biome_html_formatter/src/html/any/attribute.rscrates/biome_html_formatter/src/generated.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Implement the `FormatNodeRule<N>` trait with `fmt_fields` as the only required method; default implementations of `fmt`, `is_suppressed`, `fmt_leading_comments`, `fmt_dangling_comments`, and `fmt_trailing_comments` are provided
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_double_text_expression.rscrates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rscrates/biome_html_formatter/src/html/any/attribute_initializer.rscrates/biome_html_formatter/src/html/any/attribute.rscrates/biome_html_formatter/src/generated.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/src/lib.rs : Expose a public `format_node` function that accepts formatting options and a root syntax node, returning a `FormatResult<Formatted<Context>>` with appropriate documentation
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_double_text_expression.rscrates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rscrates/biome_html_formatter/src/html/any/attribute_initializer.rscrates/biome_html_formatter/src/html/any/attribute.rscrates/biome_html_formatter/src/generated.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: The formatter foundation relies on using the generic `Format` trait and `FormatNode` for nodes, with creation of an intermediate IR via a series of helpers
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_double_text_expression.rscrates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rscrates/biome_html_formatter/src/html/any/attribute_initializer.rscrates/biome_html_formatter/src/html/any/attribute.rscrates/biome_html_formatter/src/generated.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/src/context.rs : Define `<Language>FormatContext` struct in a `context.rs` file containing `comments` and `source_map` fields, implementing `FormatContext` and `CstFormatContext` traits
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_double_text_expression.rscrates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rscrates/biome_html_formatter/src/html/any/attribute.rscrates/biome_html_formatter/src/generated.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/src/lib.rs : Define a type alias `<Language>Formatter<'buf>` as `Formatter<'buf, <Language>FormatContext>` in the main formatter crate
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_double_text_expression.rscrates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rscrates/biome_html_formatter/src/generated.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Create a new formatter crate using the command `just new-crate biome_<language>_formatter` where `<language>` is the target language (e.g., `biome_html_formatter` for HTML)
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_double_text_expression.rscrates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rs
📚 Learning: 2025-12-21T21:15:03.796Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: CONTRIBUTING.md:0-0
Timestamp: 2025-12-21T21:15:03.796Z
Learning: Changesets should describe user-facing changes only; internal refactoring without behavior changes does not require a changeset
Applied to files:
.changeset/happy-cats-drive.md
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/tests/language.rs : Implement `TestFormatLanguage` trait in `tests/language.rs` for the formatter's test language
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rscrates/biome_html_formatter/src/html/any/attribute.rscrates/biome_html_formatter/src/generated.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Implement the `FormatLanguage` trait with `SyntaxLanguage`, `Context`, and `FormatRule` associated types for the language's formatter
Applied to files:
crates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rscrates/biome_html_formatter/src/generated.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : Use `ConditionalParsedSyntax` for syntax that is only valid in specific contexts (e.g., strict mode, file types, language versions) and call `or_invalid_to_bogus()` to convert to a bogus node if not supported
Applied to files:
crates/biome_html_parser/src/syntax/mod.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/*.ungram : Nodes for enclosing syntax errors must have the `Bogus` word, e.g., `HtmlBogusAttribute`, and must be part of a variant
Applied to files:
crates/biome_html_parser/src/syntax/mod.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : Parse rules must take a mutable reference to the parser as their only parameter and return a `ParsedSyntax`
Applied to files:
crates/biome_html_parser/src/syntax/mod.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : Parse rule functions must be prefixed with `parse_` and use the name defined in the grammar file, e.g., `parse_for_statement` or `parse_expression`
Applied to files:
crates/biome_html_parser/src/syntax/mod.rs
📚 Learning: 2025-12-19T12:53:30.413Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-12-19T12:53:30.413Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/**/*.rs : Prefix line with `#` in documentation code examples sparingly; prefer concise complete snippets
Applied to files:
crates/biome_html_parser/src/syntax/mod.rs
📚 Learning: 2025-12-19T12:53:30.413Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_analyze/CONTRIBUTING.md:0-0
Timestamp: 2025-12-19T12:53:30.413Z
Learning: Applies to crates/biome_analyze/**/*analyze/src/**/*.rs : Assist rules should detect refactoring opportunities and emit code action signals
Applied to files:
crates/biome_html_parser/src/syntax/mod.rs
📚 Learning: 2025-11-09T12:47:46.298Z
Learnt from: ematipico
Repo: biomejs/biome PR: 8031
File: crates/biome_html_parser/src/syntax/svelte.rs:140-147
Timestamp: 2025-11-09T12:47:46.298Z
Learning: In the Biome HTML parser, `expect` and `expect_with_context` consume the current token and then lex the next token. The context parameter in `expect_with_context` controls how the next token (after the consumed one) is lexed, not the current token being consumed. For example, in Svelte parsing, after `bump_with_context(T!["{:"], HtmlLexContext::Svelte)`, the next token is already lexed in the Svelte context, so `expect(T![else])` is sufficient unless the token after `else` also needs to be lexed in a specific context.
Applied to files:
crates/biome_html_parser/src/syntax/mod.rs
📚 Learning: 2025-12-19T11:31:06.239Z
Learnt from: ematipico
Repo: biomejs/biome PR: 8509
File: crates/biome_html_parser/src/syntax/svelte.rs:465-467
Timestamp: 2025-12-19T11:31:06.239Z
Learning: In the Biome HTML parser, `parse_single_text_expression_content` does not advance the parser if the current token is empty. This is intentional to support cases where an expression is optional. When calling this function, callers must check if `p.cur_text().is_empty()` after the call and manually advance the parser with `p.bump_remap(HTML_LITERAL)` if needed.
Applied to files:
crates/biome_html_parser/src/syntax/mod.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Implement the `IntoFormat<Context>` trait in `lib.rs` with implementations for `SyntaxResult` and `Option` types as part of the formatter infrastructure
Applied to files:
crates/biome_html_formatter/src/html/any/attribute_initializer.rscrates/biome_html_formatter/src/generated.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Implement the `AsFormat<Context>` trait in `lib.rs` with generic implementations for references, `SyntaxResult`, and `Option` types as provided in the formatter boilerplate code
Applied to files:
crates/biome_html_formatter/src/html/any/attribute_initializer.rscrates/biome_html_formatter/src/generated.rs
📚 Learning: 2025-11-24T18:05:27.810Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_js_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:27.810Z
Learning: Applies to crates/biome_js_formatter/**/*.rs : Do not attempt to 'fix' the code; if a token/node is known to be mandatory but is missing, return `None` instead
Applied to files:
crates/biome_html_formatter/src/html/any/attribute.rs
📚 Learning: 2025-12-04T13:29:49.287Z
Learnt from: dyc3
Repo: biomejs/biome PR: 8291
File: crates/biome_html_formatter/tests/specs/prettier/vue/html-vue/elastic-header.html:10-10
Timestamp: 2025-12-04T13:29:49.287Z
Learning: Files under `crates/biome_html_formatter/tests/specs/prettier` are test fixtures synced from Prettier and should not receive detailed code quality reviews (e.g., HTTP vs HTTPS, formatting suggestions, etc.). These files are test data meant to validate formatter behavior and should be preserved as-is.
Applied to files:
crates/biome_html_parser/tests/html_specs/error/template-langs/django/issue-8605.html
🧬 Code graph analysis (5)
crates/biome_html_formatter/src/html/lists/attribute_list.rs (2)
crates/biome_html_formatter/src/generated.rs (28)
format(28-33)format(66-71)format(104-109)format(126-128)format(155-157)format(187-192)format(209-211)format(238-243)format(276-281)format(314-319)format(352-357)format(390-396)format(430-435)format(468-473)format(506-511)format(538-543)fmt(14-20)fmt(52-58)fmt(90-96)fmt(123-123)fmt(141-147)fmt(173-179)fmt(206-206)fmt(224-230)fmt(262-268)fmt(300-306)fmt(338-344)fmt(376-382)crates/biome_html_formatter/src/html/any/attribute.rs (1)
fmt(9-18)
crates/biome_html_formatter/src/html/auxiliary/attribute_double_text_expression.rs (3)
crates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rs (1)
fmt_fields(11-30)crates/biome_html_formatter/src/generated.rs (16)
format(28-33)format(66-71)format(104-109)format(126-128)format(155-157)format(187-192)format(209-211)format(238-243)format(276-281)format(314-319)format(352-357)format(390-396)format(430-435)format(468-473)format(506-511)format(538-543)crates/biome_formatter/src/builders.rs (1)
space(606-608)
crates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rs (2)
crates/biome_html_formatter/src/html/auxiliary/attribute_double_text_expression.rs (1)
fmt_fields(11-32)crates/biome_html_formatter/src/generated.rs (16)
format(28-33)format(66-71)format(104-109)format(126-128)format(155-157)format(187-192)format(209-211)format(238-243)format(276-281)format(314-319)format(352-357)format(390-396)format(430-435)format(468-473)format(506-511)format(538-543)
crates/biome_html_parser/src/syntax/mod.rs (3)
crates/biome_formatter/src/lib.rs (2)
context(971-973)context(2133-2135)crates/biome_html_parser/src/parser.rs (1)
context(90-92)crates/biome_parser/src/lib.rs (1)
context(155-155)
crates/biome_html_formatter/src/html/any/attribute.rs (1)
crates/biome_service/src/file_handlers/html.rs (3)
node(718-718)node(730-730)node(737-737)
🪛 LanguageTool
.changeset/happy-cats-drive.md
[misspelling] ~5-~5: Use “an” instead of ‘a’ if the following word starts with a vowel sound, e.g. ‘an article’, ‘an hour’.
Context: ... }}or{ expr }`) at the top level of a HTML document no longer causes panickin...
(EN_A_VS_AN)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
- GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
- GitHub Check: Lint project (depot-windows-2022)
- GitHub Check: Documentation
- GitHub Check: Check Dependencies
- GitHub Check: Test (depot-windows-2022-16)
- GitHub Check: Test (depot-ubuntu-24.04-arm-16)
- GitHub Check: End-to-end tests
- GitHub Check: Test Node.js API
- GitHub Check: autofix
- GitHub Check: Parser conformance
🔇 Additional comments (15)
crates/biome_html_parser/tests/html_specs/error/template-langs/django/issue-8605.html (1)
1-1: LGTM! Minimal reproduction case for issue #8605.This test file appropriately captures the scenario of a Django template expression at the document root, which previously caused incorrect bogus node generation.
xtask/codegen/src/html_kinds_src.rs (1)
80-81: LGTM! New node kinds properly added.The addition of
HTML_ATTRIBUTE_DOUBLE_TEXT_EXPRESSIONandHTML_ATTRIBUTE_SINGLE_TEXT_EXPRESSIONcorrectly distinguishes attribute-context interpolations from content-context ones, addressing the root cause of issue #8605.crates/biome_html_formatter/src/html/any/attribute.rs (1)
13-14: LGTM! Generated formatter properly updated.The match arms correctly handle the new
HtmlAttributeDoubleTextExpressionandHtmlAttributeSingleTextExpressionvariants, delegating formatting appropriately.crates/biome_html_formatter/src/html/any/attribute_initializer.rs (1)
11-13: LGTM! Generated formatter correctly updated.The variant name change to
HtmlAttributeSingleTextExpressionaligns with the new attribute-context node kinds.crates/biome_html_formatter/src/html/auxiliary/mod.rs (1)
4-4: LGTM! Generated module declarations correctly added.The new
attribute_double_text_expressionandattribute_single_text_expressionmodules are properly exposed, maintaining alphabetical ordering.Also applies to: 7-7
crates/biome_html_syntax/src/attr_ext.rs (1)
11-11: LGTM!Variant rename correctly reflects the new attribute-specific text expression type introduced in this PR.
crates/biome_html_formatter/src/html/lists/attribute_list.rs (1)
63-68: LGTM!Match arms updated to use the new attribute-specific text expression variants. Formatting delegation remains consistent.
crates/biome_html_parser/src/syntax/mod.rs (2)
561-565: LGTM!Context-aware completion correctly distinguishes double text expressions inside tags (attributes) from those in regular content, fixing the bogus node issue described in #8605.
612-616: LGTM!Context-aware completion for single text expressions mirrors the double expression logic, maintaining consistency.
crates/biome_html_formatter/src/html/auxiliary/attribute_single_text_expression.rs (1)
22-29: Formatter implementation looks correct.The formatting matches the pattern for other node rules. Note: Unlike
HtmlAttributeDoubleTextExpressionwhich formats with spaces around the expression ({{ expr }}), this omits spaces ({expr}), which appears intentional for distinguishing single from double brace syntax.xtask/codegen/html.ungram (3)
165-166: LGTM!
AnyHtmlAttributealternatives correctly reference the new attribute-specific text expression node types.
187-187: LGTM!
AnyHtmlAttributeInitializercorrectly usesHtmlAttributeSingleTextExpressionas the alternative toHtmlString.
190-204: LGTM!Grammar definitions for
HtmlAttributeDoubleTextExpressionandHtmlAttributeSingleTextExpressionare well-structured and follow naming conventions. The documentation comments clearly indicate their usage contexts.crates/biome_html_formatter/src/html/auxiliary/attribute_double_text_expression.rs (1)
1-33: LGTM!The formatter implementation is clean and follows the established patterns correctly. The spacing around the expression (
{{ expr }}) is consistent with Django/Jinja2 template formatting conventions and appropriately differs from the single-text-expression variant.crates/biome_html_formatter/src/generated.rs (1)
123-135: LGTM!The generated formatting trait implementations for both new attribute text expression types follow the correct pattern and properly delegate to their respective formatter modules.
Also applies to: 206-218
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
ematipico
left a comment
There was a problem hiding this comment.
It seems there have been some regressions in the formatted
|
|
||
| }} reprehenderit voluptates minus {{console.log( short_interpolation )}} nemo.</div> | ||
| }} | ||
| reprehenderit voluptates minus {{console.log( short_interpolation )}}nemo. |
There was a problem hiding this comment.
This is a regression. There's no more space after }} anymore
There was a problem hiding this comment.
Fixed in 81cd283, I am not sure this is the right way
| Fuga magnam facilis. Voluptatem quaerat porro. | ||
| {{ |
There was a problem hiding this comment.
Newline before {{. It seems to be a regression
There was a problem hiding this comment.
I think it would be useful to have also a test that passes
|
Is it possible that your local |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
crates/biome_html_parser/tests/spec_test.rs (1)
34-40: Nice path-based test routing!The conditional override correctly enables text expression parsing for tests organised under "with-text-expressions" directories. The logic is sound and aligns well with the test fixture structure.
Optional: Consider adding a brief comment
A one-line comment explaining the override would help future maintainers:
let mut file_source = HtmlFileSource::try_from(test_case_path).unwrap_or_default(); +// Enable text expression parsing (e.g., Django-style {{ expr }}) for dedicated test fixtures if test_case_path .iter() .any(|segment| segment == "with-text-expressions")
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
crates/biome_html_parser/tests/html_specs/ok/with-text-expressions/issue-8605.html.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (2)
crates/biome_html_parser/tests/html_specs/ok/with-text-expressions/issue-8605.htmlcrates/biome_html_parser/tests/spec_test.rs
✅ Files skipped from review due to trivial changes (1)
- crates/biome_html_parser/tests/html_specs/ok/with-text-expressions/issue-8605.html
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.rs: Use inline rustdoc documentation for rules, assists, and their options
Use thedbg!()macro for debugging output in Rust tests and code
Use doc tests (doctest) format with code blocks in rustdoc comments; ensure assertions pass in tests
Files:
crates/biome_html_parser/tests/spec_test.rs
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Define `FormatHtmlSyntaxNode` struct in a `cst.rs` file implementing `FormatRule<HtmlSyntaxNode>`, `AsFormat<HtmlFormatContext>`, and `IntoFormat<HtmlFormatContext>` traits using the provided boilerplate code
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/tests/spec_tests.rs : Use the `tests_macros::gen_tests!` macro in `spec_tests.rs` to generate test functions for each specification file matching the pattern `tests/specs/<language>/**/*.<ext>`
Applied to files:
crates/biome_html_parser/tests/spec_test.rs
📚 Learning: 2025-12-04T13:29:49.287Z
Learnt from: dyc3
Repo: biomejs/biome PR: 8291
File: crates/biome_html_formatter/tests/specs/prettier/vue/html-vue/elastic-header.html:10-10
Timestamp: 2025-12-04T13:29:49.287Z
Learning: Files under `crates/biome_html_formatter/tests/specs/prettier` are test fixtures synced from Prettier and should not receive detailed code quality reviews (e.g., HTTP vs HTTPS, formatting suggestions, etc.). These files are test data meant to validate formatter behavior and should be preserved as-is.
Applied to files:
crates/biome_html_parser/tests/spec_test.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : Implement a token source struct that wraps the lexer and implements `TokenSourceWithBufferedLexer` and `LexerWithCheckpoint` for lookahead and re-lexing capabilities
Applied to files:
crates/biome_html_parser/tests/spec_test.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/tests/language.rs : Implement `TestFormatLanguage` trait in `tests/language.rs` for the formatter's test language
Applied to files:
crates/biome_html_parser/tests/spec_test.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : Use `ConditionalParsedSyntax` for syntax that is only valid in specific contexts (e.g., strict mode, file types, language versions) and call `or_invalid_to_bogus()` to convert to a bogus node if not supported
Applied to files:
crates/biome_html_parser/tests/spec_test.rs
📚 Learning: 2025-11-24T18:06:12.048Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_service/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:12.048Z
Learning: Applies to crates/biome_service/src/workspace/watcher.tests.rs : Implement watcher tests for workspace methods in watcher.tests.rs and end-to-end tests in LSP tests
Applied to files:
crates/biome_html_parser/tests/spec_test.rs
📚 Learning: 2025-11-24T18:06:03.545Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_parser/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:06:03.545Z
Learning: Applies to crates/biome_parser/**/src/**/*.rs : A parser struct must implement the `Parser` trait and save the token source, parser context, and optional parser options
Applied to files:
crates/biome_html_parser/tests/spec_test.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Create test infrastructure with `tests/specs` folder structure and `spec_test.rs`, `spec_tests.rs`, and `language.rs` files in test directories
Applied to files:
crates/biome_html_parser/tests/spec_test.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/src/context.rs : Define `<Language>FormatContext` struct in a `context.rs` file containing `comments` and `source_map` fields, implementing `FormatContext` and `CstFormatContext` traits
Applied to files:
crates/biome_html_parser/tests/spec_test.rs
📚 Learning: 2025-11-24T18:05:20.371Z
Learnt from: CR
Repo: biomejs/biome PR: 0
File: crates/biome_formatter/CONTRIBUTING.md:0-0
Timestamp: 2025-11-24T18:05:20.371Z
Learning: Applies to crates/biome_formatter/**/biome_*_formatter/Cargo.toml : Include development dependencies in `Cargo.toml` for formatter tests: `biome_formatter_test`, `biome_<language>_factory`, `biome_<language>_parser`, `biome_parser`, `biome_service`, `countme`, `iai`, `quickcheck`, `quickcheck_macros`, and `tests_macros`
Applied to files:
crates/biome_html_parser/tests/spec_test.rs
🧬 Code graph analysis (1)
crates/biome_html_parser/tests/spec_test.rs (1)
crates/biome_html_syntax/src/file_source.rs (2)
try_from(146-157)html_with_text_expressions(79-83)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
- GitHub Check: Lint project (depot-ubuntu-24.04-arm-16)
- GitHub Check: Lint project (depot-windows-2022)
- GitHub Check: Check Dependencies
- GitHub Check: Test (depot-windows-2022-16)
- GitHub Check: Test (depot-ubuntu-24.04-arm-16)
- GitHub Check: Documentation
- GitHub Check: End-to-end tests
- GitHub Check: Test Node.js API
- GitHub Check: autofix
- GitHub Check: Parser conformance
Summary
Closes #8605
The django-style interpolations (
{{ expr }}) can be placed both inside and outside HTML tags. For example:Biome have used the same syntax kind
HTML_DOUBLE_TEXT_EXPRESSIONfor the both usages. However, it's ambiguous when converting it to a bogus node:biome/crates/biome_html_syntax/src/lib.rs
Lines 59 to 69 in e0a02bf
The syntax kind does not have the context in where the node is placed, and it tried to place
HTML_BOGUS_ATTRIBUTEunderHTML_ELEMENT_LIST, which is invalid. To distinguish these, I added new syntax kindsHTML_ATTRIBUTE_DOUBLE_TEXT_EXPRESSIONandHTML_ATTRIBUTE_SINGLE_TEXT_EXPRESSION, which are only used inside a HTML tag and possibly at an attribute.Test Plan
Added a snapshot test. Plus manually tested with the reproduction in the issue.
Docs
N/A